Skip to content

feat: HTML and WASM export of Reveal slides - #10703

Merged
peter-gy merged 15 commits into
marimo-team:mainfrom
peter-gy:pgy/slide-export
Sep 3, 2026
Merged

feat: HTML and WASM export of Reveal slides#10703
peter-gy merged 15 commits into
marimo-team:mainfrom
peter-gy:pgy/slide-export

Conversation

@peter-gy

@peter-gy peter-gy commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

A notebook configured as slides currently exports as a normal vertical notebook because its saved layout is not part of the exported mount data.

This PR carries the configured layout through static HTML and WebAssembly export, then restores it through the existing layout plugins before cells render. Static HTML opens as a Reveal deck with captured outputs. WebAssembly --mode run opens the same deck and keeps Python-backed controls reactive in the browser.

Both formats preserve slide types, fragments, speaker notes, deck settings, deep links, and code visibility. Ordinary notebooks retain their normal exported shell.

Implementation

  • The CLI, server, in-app, and Pyodide export paths pass the same serialized layout through the existing mount configuration.
  • The frontend holds that layout until notebook cells are available, then lets the selected renderer plugin validate and materialize it.
  • In-app exports flush pending document changes before taking a snapshot. A full save recovers an ambiguous sync failure, and revision ordering prevents a slower auto-export from overwriting a newer file.
  • Exported decks use the existing Reveal renderer for navigation, deep links, code controls, and notes.

Speaker view

Both formats embed speaker notes in the exported HTML, so anyone with the file can read them. Static HTML enables Reveal speaker view with S.

WebAssembly keeps speaker view disabled. Reveal creates the presenter previews by loading the deck twice in iframes, which would start two more Pyodide workers and rerun the notebook independently. Those previews could diverge from the main deck and repeat side effects. Clean support would need passive preview frames supplied by the main runtime, so this change keeps one Pyodide owner per deck. We can consider this as a follow up, but for now the effort-reward ratio seemed poor.

Closes #10682

@peter-gy peter-gy added the enhancement New feature or request label Aug 30, 2026
@vercel

vercel Bot commented Aug 30, 2026

Copy link
Copy Markdown

Deployment failed for project marimo-docs with the following error:

You don't have permission to create a Preview Deployment for this Vercel project: marimo-docs.

View Documentation: https://vercel.com/docs/accounts/team-members-and-roles

@github-actions github-actions Bot added documentation Improvements or additions to documentation bash-focus Area to focus on during release bug bash labels Aug 30, 2026
@github-actions

github-actions Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

Resolve configured layouts once and serialize them through static and WebAssembly mount configs so file, HTTP, and Pyodide exports share the same fallback behavior.
Keep serialized layouts pending until cells exist, then validate and materialize them through the existing renderer plugins. Initialize mounted URL state before the first render.
Hide notebook chrome for exported decks, enable static speaker view, and synchronize deep links and code controls across static and WebAssembly startup.
Flush document transactions before layout serialization, recover ambiguous sync failures through an authoritative full save, and prevent older auto-export jobs from committing after newer state.
@peter-gy

peter-gy commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review please

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review please

@peter-gy I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 70 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread frontend/src/components/slides/reveal-component.tsx
Comment thread marimo/_server/api/endpoints/export.py
Comment thread frontend/src/core/cells/document-changes.ts
Comment thread frontend/src/core/layout/layout.ts Outdated
Comment thread marimo/_server/templates/api.py Outdated
Comment thread docs/guides/apps.md
Comment thread docs/guides/exporting/webassembly_html.md Outdated
Comment thread frontend/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts Outdated
@peter-gy

peter-gy commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review please

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review please

@peter-gy I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 70 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread frontend/src/core/cells/document-changes.ts Outdated
@peter-gy

peter-gy commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review please

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review please

@peter-gy I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 70 files

Re-trigger cubic

@peter-gy
peter-gy marked this pull request as ready for review September 1, 2026 11:09
@peter-gy
peter-gy requested a review from akshayka as a code owner September 1, 2026 11:09
Copilot AI lite review requested due to automatic review settings September 1, 2026 11:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR ensures that notebooks configured with the slides layout export as Reveal decks (static HTML and HTML+WASM), by carrying the serialized layout through export/mount configuration and restoring it via existing layout renderer plugins before cells render. It also strengthens export consistency by flushing pending document changes before snapshot/export and by preventing older auto-export generations/revisions from overwriting newer outputs.

Changes:

  • Add layout to the mount config and export request/schema plumbing so static HTML and WASM exports can rehydrate the slides layout.
  • Validate/deserialize serialized layout data via renderer plugin validators and preserve “pending” layout until cells are available.
  • Improve auto-export correctness with generation tracking, per-format revision reservation, and frontend document-change flushing before export.

Reviewed changes

Copilot reviewed 70 out of 70 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/_session/state/test_session_view.py Adds coverage for HTML auto-export staleness tracking with layout + generation handling.
tests/_server/test_templates_filename.py Updates mount-config JSON parsing expectations after template changes (no trailing comma handling).
tests/_server/templates/utils.py Adds helper to parse embedded mount config from exported HTML in tests.
tests/_server/templates/test_templates_api.py Verifies static template includes/validates layout in mount config.
tests/_server/templates/snapshots/export1.txt Snapshot update to include layout in mount config.
tests/_server/templates/snapshots/export2.txt Snapshot update to include layout in mount config.
tests/_server/templates/snapshots/export3.txt Snapshot update to include layout in mount config.
tests/_server/templates/snapshots/export4.txt Snapshot update to include layout in mount config.
tests/_server/templates/snapshots/export5.txt Snapshot update to include layout in mount config.
tests/_server/templates/snapshots/export6.txt Snapshot update to include layout in mount config.
tests/_server/api/endpoints/test_export.py Extends export endpoint tests to assert layout behavior and auto-export revision behavior.
tests/_runtime/layout/test_layout.py Adjusts layout-file reading tests to treat invalid contents as None instead of raising.
tests/_pyodide/test_pyodide_session.py Ensures Pyodide HTML export passes through and embeds serialized layout.
tests/_export/test_exporter.py Expands file export tests to cover layout resolution/inlining across export kinds.
tests/_export/test_auto_exporter.py Adds regression test ensuring newer auto-export writes supersede older ones.
tests/_cli/test_cli_export.py Updates CLI wasm HTML export test to validate embedded layout + mode.
packages/openapi/src/api.ts Updates generated OpenAPI TS types to include layout on HTML export request (and reorders schemas).
packages/openapi/api.yaml Updates OpenAPI spec to document/add layout on HTML export request (and reorders schemas).
marimo/_templates.py Adds layout to the mount config and passes it through static/wasm templates.
marimo/_session/state/session_view.py Adds auto-export generation + tracks HTML auto-export layout to avoid missing layout-driven exports.
marimo/_server/templates/api.py Validates untrusted layout input for static rendering using parse_layout_config.
marimo/_server/api/endpoints/export.py Threads layout selection into HTML export + improves auto-export correctness (generation + revision).
marimo/_schemas/export.py Adds layout to ExportAsHTMLRequest and implements fallback semantics (unset => read saved layout).
marimo/_runtime/layout/layout.py Adds parsing/validation helpers and robust layout reading + data-URI encoding helper.
marimo/_pyodide/pyodide_session.py Threads HTML export layout selection into Pyodide export path.
marimo/_export/requests.py Adds layout to HTML/WASM export request dataclasses.
marimo/_export/file.py Resolves/inlines layout files into data URIs for portable HTML/WASM exports.
marimo/_export/exporter.py Passes layout through to templates + adds per-file revisioning/locking for auto-export writes.
marimo/_cli/development/commands.py Preview command now passes app config + layout into static template.
marimo/_ast/app.py Removes inline_layout_file from InternalApp (layout inlining moved to export layer).
frontend/src/mount.tsx Hydrates serialized layout from mount config into layout state; adds kiosk query param handling.
frontend/src/core/websocket/useMarimoKernelConnection.tsx Tracks “initial run completed” to safely enable deep-link hash resolution in wasm contexts.
frontend/src/core/websocket/tests/useMarimoKernelConnection.hook.test.tsx Adds test coverage for initial-run completion tracking.
frontend/src/core/static/download-html.ts Includes flushed serialized layout in static HTML download request.
frontend/src/core/saving/save-component.tsx Serializes full saves via a queue and adds document resync boundary for ambiguous transaction failures.
frontend/src/core/saving/tests/save-component.test.ts Tests save queue serialization and failure recovery behavior.
frontend/src/core/run-app.tsx Adds option to hide header (used for exported slides).
frontend/src/core/meta/code-visibility.ts Adjusts kiosk code-visibility semantics based on runtime kind (remote vs static/wasm).
frontend/src/core/meta/tests/code-visibility.test.tsx Adds coverage for static kiosk code-visibility behavior.
frontend/src/core/layout/state.ts Introduces layout state with “pending serialized layout” to defer materialization until cells exist.
frontend/src/core/layout/layout.ts Adds helpers to resolve layout data from pending/materialized state and integrate plugin deserialization.
frontend/src/core/layout/tests/layout.test.ts Adds tests for pending layout preservation and serialization fallback behavior.
frontend/src/core/kernel/state.ts Adds atom to represent completion of the initial kernel run.
frontend/src/core/kernel/handlers.ts Uses validated layout deserialization to build layout state safely from kernel payloads.
frontend/src/core/export/layout.ts Adds helper to flush document changes before exporting and return serialized layout.
frontend/src/core/export/hooks.ts Includes flushed serialized layout in auto-export requests.
frontend/src/components/static-html/share-modal.tsx Includes flushed serialized layout in share/static export requests.
frontend/src/components/slides/speaker-view.ts Centralizes speaker-view URL/policy logic and disables speaker view for wasm.
frontend/src/components/slides/reveal-component.tsx Improves slides behavior for speaker view receivers, deep links, wasm initial hash resolution, and code-toggle binding.
frontend/src/components/slides/tests/speaker-view.test.ts Adds tests for speaker-view URL building and runtime policy.
frontend/src/components/slides/tests/reveal-component.test.ts Adds unit coverage for code-toggle keybinding synchronization and updated code-availability logic.
frontend/src/components/pages/run-page.tsx Hides static banner/header/watermark when running exported slides.
frontend/src/components/editor/renderers/types.ts Adds isLayoutType helper and strongly-typed layout type list.
frontend/src/components/editor/renderers/slides-layout/types.ts Makes slides layout parsing forward-compatible by dropping invalid fields while preserving unknown keys.
frontend/src/components/editor/renderers/slides-layout/slides-layout.tsx Avoids controlling deck index during receiver/deep-link initialization to prevent navigation conflicts.
frontend/src/components/editor/renderers/slides-layout/tests/plugin.test.ts Updates slides plugin tests for permissive parsing and invalid-data fallback behavior.
frontend/src/components/editor/renderers/plugins.ts Validates serialized layouts before deserialization; falls back to initial layout on invalid data.
frontend/src/components/editor/renderers/grid-layout/plugin.tsx Makes grid layout parsing more resilient and normalizes optional fields.
frontend/src/components/editor/renderers/grid-layout/tests/plugin.test.ts Adds coverage for grid layout validation/normalization behavior.
frontend/src/components/editor/renderers/cells-renderer.tsx Uses shared helpers to resolve layout type/data and apply pending layout once cells exist.
frontend/src/components/editor/actions/export-dialog/use-export-dialog.ts Threads layout capture into export-dialog request pipeline.
frontend/src/components/editor/actions/export-dialog/export-notebook.ts Includes serialized layout in HTML export requests.
frontend/src/components/editor/actions/export-dialog/tests/export-notebook.test.ts Verifies HTML export requests include layout and that non-HTML exports do not.
frontend/src/tests/mount.test.ts Adds tests for layout hydration from mount config and kiosk-mode initialization.
frontend/e2e-tests/slides.spec.ts Adds Playwright e2e coverage for static HTML export opening as a Reveal deck without banners/watermark.
docs/guides/exporting/webassembly_html.md Documents slides behavior and speaker-notes visibility in wasm HTML exports.
docs/guides/exporting/static_html.md Documents slides behavior and speaker-notes visibility in static HTML exports.
docs/guides/apps.md Adds “Export slides” docs covering both static HTML and wasm exports and speaker-view limitations.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tests/_export/test_exporter.py
mscolnick
mscolnick previously approved these changes Sep 1, 2026
Comment thread docs/guides/apps.md Outdated
Comment thread frontend/src/components/editor/renderers/grid-layout/plugin.tsx
Comment thread frontend/src/components/editor/renderers/slides-layout/types.ts
Comment thread frontend/src/components/slides/reveal-component.tsx
Comment thread frontend/src/core/layout/layout.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 70 out of 70 changed files in this pull request and generated 2 comments.

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

marimo/_server/api/endpoints/export.py:352

  • This rename guard runs before the awaited threaded file write. For a large export, the notebook can be renamed after this check while _write_file_sync is still running, leaving the obsolete export at the old path despite the intended skip. Commit via a temporary file only after revalidating the captured filename on the event loop, or invalidate/cancel the reserved revision as part of rename handling.
    frontend/src/components/slides/reveal-component.tsx:490
  • The new WebAssembly-only startup branch is not exercised end to end: the added browser test covers static HTML, while the hook test only toggles the completion atom. Please add an html-wasm --mode run browser test that opens a slides export at a deep link and interacts with a Python-backed control; otherwise regressions where the deck never resolves its hash or loses reactivity will pass the current suite.
  const initialRunCompleted = useAtomValue(initialRunCompletedAtom);
  const canResolveInitialHash = runtimeKind !== "wasm" || initialRunCompleted;
  const deckPlugins = useMemo(
    () => (kioskMode || !supportsSpeakerView(runtimeKind) ? [] : [RevealNotes]),

Comment thread frontend/src/core/saving/save-component.tsx Outdated
Comment thread frontend/src/core/saving/save-component.tsx Outdated
Light2Dark
Light2Dark previously approved these changes Sep 2, 2026

@Light2Dark Light2Dark left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good, just wording nits.

Comment thread docs/guides/apps.md Outdated
Comment thread docs/guides/apps.md Outdated
Comment thread docs/guides/apps.md Outdated
Comment thread docs/guides/exporting/webassembly_html.md Outdated
Comment thread docs/guides/exporting/static_html.md
Comment thread docs/guides/exporting/static_html.md Outdated
@peter-gy
peter-gy merged commit 24d3abc into marimo-team:main Sep 3, 2026
67 of 69 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bash-focus Area to focus on during release bug bash documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Adding the option to export slides as HTML

4 participants